package com.clas.liu.myapplication.view.widget;

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView;

/**
 * 自定义的图片放大的查看
 * Created by liu on 2019/3/14.
 */

public class MyImageView extends android.support.v7.widget.AppCompatImageView implements
        ScaleGestureDetector.OnScaleGestureListener,View.OnTouchListener{

    //控件宽度
    private int mWidth;
    //高度
    private int mHeight;
    private Drawable mDrawable;
    private int mDrawableWidth;
    private int mDrawableHeight;
    //初始化缩放值
    private float mScale;
    //双击图片的缩放值
    private float mDoubleClickScale;
    //最大的缩放值
    private float mMaxScale;
    private float mMinScale;
    //用于手势滑动的监听
    private  ScaleGestureDetector scaleGestureDetector;
    //矩阵
    private Matrix matrix;

    //移动
    private float downX;
    private float downY;
    private float nowMovingX;
    private float nowMovingY;
    private float lastMovedX;
    private float lastMovedY;
    private boolean isFirstMove = false;


    public MyImageView(Context context) {
        this(context,null);
    }

    public MyImageView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public MyImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setOnTouchListener(this);
        scaleGestureDetector = new ScaleGestureDetector(context,this);
        initListener();
    }

    private void initListener() {
        setScaleType(ScaleType.MATRIX);
        //添加观察者,用于获取控件的宽度和高度，当一个视图树的布局发生改变时，可以被监听到
        getViewTreeObserver().addOnGlobalLayoutListener(
                new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                getViewTreeObserver().removeOnGlobalLayoutListener(
                        this);
                mWidth = getWidth();
                mHeight = getHeight();
                mDrawable = getDrawable();
                if(mDrawable ==null){
                    return;
                }
                mDrawableWidth = mDrawable.getIntrinsicWidth();
                mDrawableHeight = mDrawable.getIntrinsicHeight();
                initImageViewSize();
                moveToCenter();
            }
        });


    }

    private void moveToCenter() {
        final float dx = mWidth/2 - mDrawableWidth/2;
        final float dy = mHeight/2 - mDrawableHeight/2;
        matrix = new Matrix();
        matrix.postTranslate(dx,dy);

        matrix.postScale(mScale,mScale,mWidth/2,mHeight/2);
        setImageMatrix(matrix);

    }

    /**
     * 初始化图片的大小
     */
    private void initImageViewSize() {
        if (mDrawable == null)
            return;
        float scale = 1.0f;
        if(mDrawableWidth > mWidth && mDrawableHeight < mHeight)
            scale = mWidth * 1.0f / mDrawableWidth;
        else if (mDrawableWidth < mWidth && mDrawableHeight > mHeight)
            scale =mHeight * 1.0f / mDrawableHeight;
        else if (mDrawableWidth > mWidth && mDrawableHeight > mHeight)
            scale = Math.min(mWidth * 1.0f / mDrawableWidth,mHeight * 1.0f / mDrawableHeight);
        else if(mDrawableWidth < mWidth && mDrawableHeight < mHeight)
            scale = Math.min(mWidth * 1.0f / mDrawableWidth,mHeight * 1.0f / mDrawableHeight);
        mScale = scale;
        mMaxScale = mScale * 3.0f;
        mMinScale = mScale * 0.5f;

    }

    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        if(mDrawable == null){
            return true;
        }
        //系统定义的缩放值
        float scaleFactor = detector.getScaleFactor();
        //获取已经缩放的值
        float scale = getmScale();
        float scaleResult = scale * scaleFactor;
        if (scaleResult >= mMaxScale && scaleFactor> 1.0f)
            scaleFactor = mMaxScale/scale;
        if (scaleResult <= mMinScale && scaleFactor < 1.0f)
            scaleFactor = mMinScale / scale;
        matrix.postScale(scaleFactor,scaleFactor,detector.getFocusX(),detector.getFocusY());

        RectF f = getRectf(matrix);
        float dx = 0.0f;
        float dy = 0.0f;
        //缩放后图片大小大于了控件
         if(f.height() >= mHeight){
             //顶部还留有空隙
             if(f.top >0 ){
                 dy = -f.top;
             }
             if(f.bottom <mHeight){
                 dy = mHeight-f.bottom;
             }
         }
        if(f.width() >= mWidth){
            if(f.left >0 ){
                dx = -f.left;
            }
            if(f.right <mWidth){
                dx = mWidth-f.right;
            }
        }
        if (f.width() < mWidth) {
            dx = mWidth / 2 - f.right + f.width() / 2;
        }
        if (f.height() < mHeight) {
            dy = mHeight / 2 - f.bottom + f.height() / 2;
        }
        matrix.postTranslate(dx,dy);
        setImageMatrix(matrix);
        return true;
    }

    private RectF getRectf(Matrix matrix) {
        RectF f = new RectF();
        if(mDrawable == null)
            return null;
        f.set(0,0,mDrawableWidth,mDrawableHeight);
        matrix.mapRect(f);
        return f;

    }

    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {
        float scale = getmScale();
        if (scale < mScale) {
            matrix.postScale(mScale / scale, mScale / scale, mWidth / 2, mHeight / 2);
            setImageMatrix(matrix);
        }
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        switch ((event.getAction() & MotionEvent.ACTION_MASK)){
            case MotionEvent.ACTION_DOWN:
                isFirstMove = false;
                downX = event.getX();
                downY = event.getY();
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                isFirstMove = false;
                break;
            case MotionEvent.ACTION_MOVE:
                Log.i("test", "onTouch: "+isFirstMove);
                nowMovingX = event.getX();
                nowMovingY = event.getY();
                if (!isFirstMove){
                    isFirstMove= true;
                    lastMovedX = downX;
                    lastMovedY = downY;
                }
                float dx = 0.0f;
                float dy = 0.0f;
                RectF rectF = getRectf(matrix);
                //判断滑动方向
                final float scrollX = nowMovingX-lastMovedX;
                final float scrollY = nowMovingY-lastMovedY;
                if (rectF.height() > mHeight && canSmoothY())
                    dy = nowMovingY - lastMovedY;
                if (rectF.width() > mWidth && canSmoothX())
                    dx = nowMovingX - lastMovedX;
                matrix.postTranslate(dx,dy);
                reTranslate(dx,dy);
                lastMovedY = nowMovingY;
                lastMovedX = nowMovingX;
                break;
            case MotionEvent.ACTION_UP:
                break;
            case MotionEvent.ACTION_POINTER_UP:
                isFirstMove = false;
                break;
        }
        return  scaleGestureDetector.onTouchEvent(event);
    }

    //纠正出界的x和y
    private void reTranslate(float dx, float dy) {
        if(!canSmoothX())
            matrix.postTranslate(-dx,0);
        if (!canSmoothY())
            matrix.postTranslate(0,-dy);
        setImageMatrix(matrix);
    }

    //判断x方向上还能不能滑动
    private boolean canSmoothX() {
        RectF rectF = getRectf(matrix);
        Log.i("test", "onTouch: cY"+rectF.left+" ");
        if (rectF.left >0 || rectF.right <getWidth())
            return false;
        return true;
    }

    //判断y方向上还能不能滑动
    private boolean canSmoothY() {
        RectF rectF = getRectf(matrix);
        if (rectF.top >0 || rectF.bottom <getHeight())
            return false;
        return true;
    }


    //获取当前缩放的值
    public float getmScale() {
        float[] floats = new float[9];
        matrix.getValues(floats);
        return floats[Matrix.MSCALE_X];
    }
}
